Qt音视频开发08

您所在的位置:网站首页 qt ffmpeg视频播放器 Qt音视频开发08

Qt音视频开发08

#Qt音视频开发08| 来源: 网络整理| 查看: 265

一、前言

最初编写这套视频解析组件的时候,面对的场景是视频监控行业,对应设备都是网络监控摄像机,传过来的都是rtsp这种视频流,做过这一块的人都知道,打开某个视频流默认耗时比较大,基本上在2s左右,那是因为ffmpeg接口内部读取的最大数据量 formatCtx->probesize(从源文件中读取的最大字节数)值是5000000,导致这里卡很久最耗时,可以调小来加快打开速度。还有一个参数就是从文件中读取的最大时长 formatCtx->max_analyze_duration,改成5个单位即可,5 * AV_TIME_BASE。当然这参数也不是一层不变的,需要根据实际的网络状态好坏来设置,ffmpeg内部接口值很大就是尽量考虑了网络环境很差的情况,所以默认值很大。基本上改了这两个参数以后在局域网中打开1080P的主码流都只要0.5s左右,比之前的2s提升了3倍以上。

除了对打开速度进行特别优化之外,还有一块就是超时回调,毕竟实时的视频流这种,严重依赖网络环境的好坏,一旦网络环境不好,或者网络设备坏了,网线拔了,很容易卡主读取,在用 avformat_open_input 打开视频流的阶段也特别容易卡主很久,windows上默认30s左右,这么久肯定不能接受,所以需要有个机制可以自由控制最大等待时间,设置超时回调 formatCtx->interrupt_callback.callback 就很有必要的。

以前采用过的策略是打开前去主动连接对应的IP地址和端口,通了说明设备在线,这种策略只适用于打开的时候,如果是运行过程中网络环境变坏了或者网线拔了之类的,依然识别不到,不可能开个定时器或者线程去检测,那样就太垃圾了,所以采用超时回调的做法是最好的最万能的。

二、效果图

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

三、体验地址 国内站点:https://gitee.com/feiyangqingyun 国际站点:https://github.com/feiyangqingyun 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_demo/bin_linux_video。 四、相关代码 bool FFmpegThread::initInput() { //实例化格式处理上下文 formatCtx = avformat_alloc_context(); //设置超时回调(有些不存在的地址或者网络不好的情况下要卡很久) formatCtx->interrupt_callback.callback = FFmpegHelper::avinterruptCallBackFun; formatCtx->interrupt_callback.opaque = this; //先判断是否是本地摄像头 AVInputFormatx *ifmt = NULL; if (videoType == VideoType_Camera) { #if defined(Q_OS_WIN) //ifmt = av_find_input_format("vfwcap"); ifmt = av_find_input_format("dshow"); #elif defined(Q_OS_LINUX) //可以打开cheese程序查看本地摄像头(如果是在虚拟机中需要设置usb选项3.1) //ifmt = av_find_input_format("v4l2"); ifmt = av_find_input_format("video4linux2"); #elif defined(Q_OS_MAC) ifmt = av_find_input_format("avfoundation"); #endif } //打开输入(通过标志位控制回调那边做超时判断) //其他地方调用 formatCtx->url formatCtx->filename 可以拿到设置的地址(两个变量值一样) tryOpen = true; QByteArray urlData = VideoHelper::getRightUrl(videoType, videoUrl).toUtf8(); int result = avformat_open_input(&formatCtx, urlData.data(), ifmt, &options); tryOpen = false; if (result //接口内部读取的最大数据量(从源文件中读取的最大字节数) //默认值5000000导致这里卡很久最耗时(可以调小来加快打开速度) formatCtx->probesize = 50000; //从文件中读取的最大时长(单位为 AV_TIME_BASE units) formatCtx->max_analyze_duration = 5 * AV_TIME_BASE; //内部读取的数据包不放入缓冲区 //formatCtx->flags |= AVFMT_FLAG_NOBUFFER; } //获取流信息 result = avformat_find_stream_info(formatCtx, NULL); if (result useSync = false; } //设置了最快速度则不启用音视频同步 if (decodeType == DecodeType_Fast2) { useSync = false; } //有些格式不支持硬解码 if (formatName.contains("rm") || formatName.contains("avi") || formatName.contains("webm")) { hardware = "none"; } //本地摄像头设备解码出来的直接就是yuv显示不需要硬解码 if (videoType == VideoType_Camera) { useSync = false; hardware = "none"; } //过低版本不支持硬解码 #if (FFMPEG_VERSION_MAJOR duration / AV_TIME_BASE; duration = duration * 1000; if (getIsFile()) { //文件必须要音视频同步 useSync = true; emit receiveDuration(duration); } QString msg = QString("格式: %1 时长: %2 秒 加速: %3").arg(formatName).arg(duration / 1000).arg(hardware); debug("文件信息", msg); return true; } int FFmpegHelper::avinterruptCallBackFun(void *ctx) { #ifdef videoffmpeg FFmpegThread *thread = (FFmpegThread *)ctx; //2021-9-29 增加先判断是否尝试停止线程,有时候不存在的地址反复打开关闭会卡主导致崩溃 //多了这个判断可以立即停止 if (thread->getTryStop()) { thread->debug("主动停止", ""); return 1; } //打开超时判定和读取超时判定 if (thread->getTryOpen()) { //时间差值=当前时间-开始解码的时间(单位微秒) qint64 offset = av_gettime() - thread->getStartTime(); int timeout = thread->getConnectTimeout() * 1000; //没有设定对应值的话限定最小值3秒 timeout = (timeout timeout) { //thread->debug("打开超时", QString("设置: %1 当前: %2").arg(timeout).arg(offset)); return 1; } } else if (thread->getTryRead()) { //时间差值=当前时间-最后一次读取的时间(单位毫秒) QDateTime now = QDateTime::currentDateTime(); qint64 offset = thread->getLastTime().msecsTo(now); int timeout = thread->getReadTimeout(); //没有设定对应值的话限定最小值3秒 timeout = (timeout timeout) { //thread->debug("读取超时", QString("设置: %1 当前: %2").arg(timeout).arg(offset)); return 1; } } #endif return 0; } 五、功能特点 5.1 基础功能 支持各种音频视频文件格式,比如mp3、wav、mp4、asf、rm、rmvb、mkv等。 支持本地摄像头设备,可指定分辨率、帧率。 支持各种视频流格式,比如rtp、rtsp、rtmp、http等。 本地音视频文件和网络音视频文件,自动识别文件长度、播放进度、音量大小、静音状态等。 文件可以指定播放位置、调节音量大小、设置静音状态等。 支持倍速播放文件,可选0.5倍、1.0倍、2.5倍、5.0倍等速度,相当于慢放和快放。 支持开始播放、停止播放、暂停播放、继续播放。 支持抓拍截图,可指定文件路径,可选抓拍完成是否自动显示预览。 支持录像存储,手动开始录像、停止录像,部分内核支持暂停录像后继续录像,跳过不需要录像的部分。 支持无感知切换循环播放、自动重连等机制。 提供播放成功、播放完成、收到解码图片、收到抓拍图片、视频尺寸变化、录像状态变化等信号。 多线程处理,一个解码一个线程,不卡主界面。 5.2 特色功能 同时支持多种解码内核,包括qmedia内核(Qt4/Qt5/Qt6)、ffmpeg内核(ffmpeg2/ffmpeg3/ffmpeg4/ffmpeg5)、vlc内核(vlc2/vlc3)、mpv内核(mpv1/mp2)、海康sdk、easyplayer内核等。 非常完善的多重基类设计,新增一种解码内核只需要实现极少的代码量,就可以应用整套机制。 同时支持多种画面显示策略,自动调整(原始分辨率小于显示控件尺寸则按照原始分辨率大小显示,否则等比例缩放)、等比例缩放(永远等比例缩放)、拉伸填充(永远拉伸填充)。所有内核和所有视频显示模式下都支持三种画面显示策略。 同时支持多种视频显示模式,句柄模式(传入控件句柄交给对方绘制控制)、绘制模式(回调拿到数据后转成QImage用QPainter绘制)、GPU模式(回调拿到数据后转成yuv用QOpenglWidget绘制)。 支持多种硬件加速类型,ffmpeg可选dxva2、d3d11va等,mpv可选auto、dxva2、d3d11va,vlc可选any、dxva2、d3d11va。不同的系统环境有不同的类型选择,比如linux系统有vaapi、vdpau,macos系统有videotoolbox。 解码线程和显示窗体分离,可指定任意解码内核挂载到任意显示窗体,动态切换。 支持共享解码线程,默认开启并且自动处理,当识别到相同的视频地址,共享一个解码线程,在网络视频环境中可以大大节约网络流量以及对方设备的推流压力。国内顶尖视频厂商均采用此策略。这样只要拉一路视频流就可以共享到几十个几百个通道展示。 自动识别视频旋转角度并绘制,比如手机上拍摄的视频一般是旋转了90度的,播放的时候要自动旋转处理,不然默认是倒着的。 自动识别视频流播放过程中分辨率的变化,在视频控件上自动调整尺寸。比如摄像机可以在使用过程中动态配置分辨率,当分辨率改动后对应视频控件也要做出同步反应。 音视频文件无感知自动切换循环播放,不会出现切换期间黑屏等肉眼可见的切换痕迹。 视频控件同时支持任意解码内核、任意画面显示策略、任意视频显示模式。 视频控件悬浮条同时支持句柄、绘制、GPU三种模式,非绝对坐标移来移去。 本地摄像头设备支持指定设备名称、分辨率、帧率进行播放。 录像文件同时支持打开的视频文件、本地摄像头、网络视频流等。 瞬间响应打开和关闭,无论是打开不存在的视频或者网络流,探测设备是否存在,读取中的超时等待,收到关闭指令立即中断之前的操作并响应。 支持打开各种图片文件,支持本地音视频文件拖曳播放。 视频控件悬浮条自带开始和停止录像切换、声音静音切换、抓拍截图、关闭视频等功能。 音频组件支持声音波形值数据解析,可以根据该值绘制波形曲线和柱状声音条,默认提供了声音振幅信号。 各组件中极其详细的打印信息提示,尤其是报错信息提示,封装的统一打印格式。针对现场复杂的设备环境测试极其方便有用,相当于精确定位到具体哪个通道哪个步骤出错。 代码框架和结构优化到最优,性能强悍,持续迭代更新升级。 源码支持Qt4、Qt5、Qt6,兼容所有版本。 5.3 视频控件 可动态添加任意多个osd标签信息,标签信息包括名字、是否可见、字号大小、文本文字、文本颜色、标签图片、标签坐标、标签格式(文本、日期、时间、日期时间、图片)、标签位置(左上角、左下角、右上角、右下角、居中、自定义坐标)。 可动态添加任意多个图形信息,这个非常有用,比如人工智能算法解析后的图形区域信息直接发给视频控件即可。图形信息支持任意形状,直接绘制在原始图片上,采用绝对坐标。 图形信息包括名字、边框大小、边框颜色、背景颜色、矩形区域、路径集合、点坐标集合等。 每个图形信息都可指定三种区域中的一种或者多种,指定了的都会绘制。 内置悬浮条控件,悬浮条位置支持顶部、底部、左侧、右侧。 悬浮条控件参数包括边距、间距、背景透明度、背景颜色、文本颜色、按下颜色、位置、按钮图标代码集合、按钮名称标识集合、按钮提示信息集合。 悬浮条控件一排工具按钮可自定义,通过结构体参数设置,图标可选图形字体还是自定义图片。 悬浮条按钮内部实现了录像切换、抓拍截图、静音切换、关闭视频等功能,也可以自行在源码中增加自己对应的功能。 悬浮条按钮对应实现了功能的按钮,有对应图标切换处理,比如录像按钮按下后会切换到正在录像中的图标,声音按钮切换后变成静音图标,再次切换还原。 悬浮条按钮单击后都用名称唯一标识作为信号发出,可以自行关联响应处理。 悬浮条空白区域可以显示提示信息,默认显示当前视频分辨率大小,可以增加帧率、码流大小等信息。 视频控件参数包括边框大小、边框颜色、焦点颜色、背景颜色(默认透明)、文字颜色(默认全局文字颜色)、填充颜色(视频外的空白处填充黑色)、背景文字、背景图片(如果设置了图片优先取图片)、是否拷贝图片、缩放显示模式(自动调整、等比例缩放、拉伸填充)、视频显示模式(句柄、绘制、GPU)、启用悬浮条、悬浮条尺寸(横向为高度、纵向为宽度)、悬浮条位置(顶部、底部、左侧、右侧)。 5.4 内核ffmpeg 支持各种音视频文件、本地摄像头设备,各种视频流网络流。 支持开始播放、暂停播放、继续播放、停止播放、设置播放进度、倍速播放。 可设置音量、静音切换、抓拍图片、录像存储。 自动提取专辑信息比如标题、艺术家、专辑、专辑封面,自动显示专辑封面。 完美支持音视频同步和倍速播放。 解码策略支持速度优先、质量优先、均衡处理、最快速度。 支持手机视频旋转角度显示,比如一般手机拍摄的视频是旋转了90度的,解码显示的时候需要重新旋转90度才是正的。 自动转换yuv420格式,比如本地摄像头是yuyv422格式,有些视频文件是xx格式,统一将非yuv420格式转换,然后再进行处理。 支持硬解码dxva2、d3d11va等,性能极高尤其是大分辨率比如4K视频。 视频响应极低延迟0.2s左右,极速响应打开视频流0.5s左右,专门做了优化处理。 硬解码和GPU绘制组合,极低CPU占用,比海康大华等客户端更优。 支持视频流中的各种音频格式,AAC、PCM、G.726、G.711A、G.711Mu、G.711ulaw、G.711alaw、MP2L2等都支持,推荐选择AAC兼容性跨平台性最好。 视频存储支持yuv、h264、mp4多种格式,音频存储支持pcm、wav、aac多种格式。默认视频mp4格式、音频aac格式。 支持分开存储音频视频文件,也支持合并到一个mp4文件,默认策略是无论何种音视频文件格式存储,最终都转成mp4及aac格式,然后合并成音视频一起的mp4文件。 支持本地摄像头实时视频显示带音频输入输出,音视频录制合并到一个mp4文件。 支持H264/H265编码(现在越来越多的监控摄像头是H265视频流格式)生成视频文件,内部自动识别切换编码格式。 自动识别视频流动态分辨率改动,重新打开视频流。 支持用户信息中包含特殊字符(比如用户信息中包含+#@等字符)的视频流播放,内置解析转义处理。 纯qt+ffmpeg解码,非sdl等第三方绘制播放依赖,gpu绘制采用qopenglwidget,音频播放采用qaudiooutput。 同时支持ffmpeg2、ffmpeg3、ffmpeg4、ffmpeg5版本,全部做了兼容处理。如果需要支持xp需要选用ffmpeg3及以下。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3